﻿using FreeDream.Common;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FreeDream.Infrastructure
{
    public static class AuthenticationJWTSetup
    {
        public static void AddAuthenticationJWTSetup(this IServiceCollection services)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            var symmetricKeyAsBase64 = AppSettings.App(new string[] { "Audience", "Secret" });
            var keyByteArray = Encoding.UTF8.GetBytes(symmetricKeyAsBase64);
            var signingKey = new SymmetricSecurityKey(keyByteArray);
            var issuer = AppSettings.App(new string[] { "Audience", "Issuer" });
            var audience = AppSettings.App(new string[] { "Audience", "Audience" });

            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

            // 令牌验证参数
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,
                ValidateIssuer = true,
                ValidIssuer = issuer,//发行人
                ValidateAudience = true,
                ValidAudience = audience,//订阅人
                ValidateLifetime = true,
                ClockSkew = TimeSpan.FromSeconds(30 * 60),   //ClockSkew 属性，默认是5分钟缓冲
                RequireExpirationTime = false,
            };

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                //options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
             // 添加JwtBearer服务
             .AddJwtBearer(o =>
             {
                 o.TokenValidationParameters = tokenValidationParameters;
                 o.Events = new JwtBearerEvents
                 {
                     OnChallenge = context =>
                     {
                         context.Response.Headers.Add("Token-Error", context.ErrorDescription);
                         return Task.CompletedTask;
                     },
                     OnMessageReceived = (context) =>
                     {
                         Console.WriteLine($"jwt OnMessageReceived {DateTime.Now}");
                         return Task.CompletedTask;
                     },
                     OnAuthenticationFailed = context =>
                     {
                         var jwtHandler = new JwtSecurityTokenHandler();
                         var token = context.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");

                         if (!string.IsNullOrWhiteSpace(token) && jwtHandler.CanReadToken(token))
                         {
                             var jwtToken = jwtHandler.ReadJwtToken(token);

                             if (jwtToken.Issuer != issuer)
                             {
                                 context.Response.Headers.Add("Token-Error-Iss", "issuer is wrong!");
                             }

                             if (jwtToken.Audiences.FirstOrDefault() != audience)
                             {
                                 context.Response.Headers.Add("Token-Error-Aud", "Audience is wrong!");
                             }
                         }

                         // 如果过期，则把<是否过期>添加到，返回头信息中
                         if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                         {
                             context.Response.Headers.Add("Token-Expired", "true");
                         }
                         return Task.CompletedTask;
                     },
                     OnTokenValidated = context =>
                     {
                         var loginUser = context.HttpContext.RequestServices.GetService<LoginUser>();
                         ////loginUser.UserId = context.SecurityToken.Id;
                         //var claims = context.Principal?.Claims;
                         //var userData = claims?.FirstOrDefault(m => m.Type == System.Security.Claims.ClaimTypes.UserData)?.Value;
                         //loginUser = System.Text.Json.JsonSerializer.Deserialize<LoginUser>(userData);
                         //var claims2 = context.HttpContext.User.Claims.ToList();

                         //var res = context.HttpContext.GetClaims().ToList();
                         Console.WriteLine($"OnTokenValidated{DateTime.Now}");
                         return Task.CompletedTask;
                     }
                 };


             });
            //.AddScheme<AuthenticationSchemeOptions, ApiResponseHandler>(nameof(ApiResponseHandler), o => { });

            //services.AddScoped<LoginUser>();
            //services.AddSingleton<LoginUserHelper>();
        }
    }
}
